2026-09-27 · class-notes, powershell, month-of-lunches, windows, objects, get-member, sort-object, select-object
Full class notes for MoL ch. 8: what objects are, Get-Member, properties and methods, Sort-Object, Select-Object, and format-last discipline.
How these notes were made: the material supplied for this lesson was the chapter's own heading list — "What are objects?", "Understanding why PowerShell uses objects", "Discovering objects: Get-Member", "Using object attributes or properties", "Using object actions or methods", "Sorting objects", "Selecting the properties you want", "Objects until the end", "Common points of confusion" — with an explicit instruction to draft the content from general knowledge rather than a transcript. These notes follow that structure, but the explanations are written from general knowledge of PowerShell's object model, not reproduced or paraphrased from Don Jones and Jeffery Hicks's actual book text, which was not supplied. Worth checking against your own copy of the chapter for their specific wording and examples.
Class notes · Learn Windows PowerShell in a Month of Lunches (3rd ed.), Don Jones and Jeffery Hicks · Chapter 8
Quick reference: the short version of this lesson lives in the Learn PowerShell resource sheets. This follows Chapter 7 (Adding Commands) and returns to something touched on back in Chapter 6 (The Pipeline) — that the pipeline passes objects, not text — and explains what an object actually is and how to work with one directly.
By the end of these notes you should be able to:
Get-Member to discover an object's properties and methods.An object is a single "thing" that bundles together data (its properties) and actions (its methods). A running process, a file, a service, a user account — each of these, represented inside PowerShell, is an object carrying properties that describe it (a process's name, its ID, how much memory it is using) and methods that let you do something to it (stop it, for instance).
This is different from a traditional command-line shell, where a command's
output is just plain text you would have to parse yourself (with tools
like grep, awk, or regular expressions) to pull out the piece of
information you actually want.
When one PowerShell command's output feeds into another via the pipeline, it is not sending text across — it is sending the actual objects, with all their properties intact. That means the next command in the pipeline can work directly with structured data (a process's exact CPU time as a number, say) rather than having to re-parse a line of formatted text to extract it.
Traditional shell (text) vs PowerShell (objects):
Text pipeline: command | grep "pattern" | awk '{print $3}'
(each stage must parse text again)
Object pipeline: Get-Process | Where-Object {$_.CPU -gt 10}
(CPU is already a real number - no parsing needed)
This is the practical payoff of everything covered back in the Pipeline chapter: filtering, sorting, and selecting all work reliably because the data stays structured the whole way through, rather than being reduced to text and reconstructed at each step.
Given an unfamiliar object, Get-Member (commonly aliased gm) reveals
every property and method that object has:
Get-Process | Get-Member
The output lists each member's name, its member type (Property, Method, and others), and, for properties, its data type. This is the standard way to answer "what can I actually do with this thing?" whenever you are working with an object type you have not used before.
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Kill Method void Kill()
Id Property int Id {get;}
ProcessName Property string ProcessName {get;}
CPU Property double CPU {get;}
Exam tip: run
Get-Memberon one item of a collection you are exploring, not the whole collection —Get-Process | Get-Memberworks fine because PowerShell examines the object type, but conceptually you are asking "what is one of these things made of," not "list every process's members separately."
Properties are the data a property holds about the object — accessed with
dot notation, $object.PropertyName:
$proc = Get-Process -Name notepad
$proc.Id # the process ID
$proc.CPU # CPU time used
$proc.ProcessName # the process name
Inside a pipeline, the special variable $_ represents "the current
object", letting you reference its properties without storing it in a
variable first:
Get-Process | Where-Object { $_.CPU -gt 10 }
Properties are also what you see when a command's output is displayed on screen — PowerShell automatically chooses a default set of properties to show for each object type, formatted as a table or a list.
Methods are actions the object can perform, called with dot notation followed by parentheses — even if the method needs no arguments:
$proc = Get-Process -Name notepad
$proc.Kill() # stop the process
If a method needs arguments, they go inside those parentheses:
$service.Start()
$string.Replace("old", "new")
Caution: forgetting the parentheses after a method name (
$proc.Kill, without()) does not call the method — PowerShell just shows you a description of the method itself, which is a common source of "why didn't that actually do anything" confusion.
Sort-Object (aliased sort) sorts objects by one or more of their
properties, rather than sorting lines of text:
Get-Process | Sort-Object -Property CPU
Get-Process | Sort-Object -Property CPU -Descending
Get-Process | Sort-Object -Property Company, CPU
Because sorting operates on the actual property value (a real number for
CPU time, for instance), the ordering is numerically correct — unlike sorting
plain text, which would order "9" after "10" alphabetically.
Select-Object (aliased select) narrows an object down to just the
properties you actually care about, or limits how many objects come through:
Get-Process | Select-Object -Property Name, Id, CPU
Get-Process | Select-Object -First 5
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
Get-Process | Select-Object -ExpandProperty ProcessName
-ExpandProperty is worth calling out specifically: rather than returning an
object with just that one property, it returns the raw values of that
property directly — useful when you want a plain list of names (or similar)
rather than a table with a single column.
Get-Process |
Sort-Object -Property CPU -Descending |
Select-Object -First 5 -Property ProcessName, CPU
Read left to right: get every process, sort them by CPU time (highest first), then keep only the top five, showing only their name and CPU columns. Each stage narrows the data further, working with real objects and real property values the entire way.
Throughout most of a PowerShell pipeline, you are working with genuine objects, with all their properties and methods intact — that is true all the way up until the point where something actually needs to display them.
The Format-* cmdlets (Format-Table, Format-List, Format-Wide) convert
objects into display-only output meant purely for the screen. Once that
conversion happens, the result is no longer the original object — you
cannot meaningfully pipe a Format-* cmdlet's output into something that
expects real objects (Sort-Object, Where-Object, Select-Object, and so
on).
Exam tip: the practical rule this produces is simple and important:
Format-*cmdlets go last in a pipeline, after every filtering, sorting and property selection is already done. Put one earlier by accident, and later stages silently receive formatting objects instead of the real data — a classic, confusing PowerShell mistake.
Correct order:
Get-Process | Sort-Object CPU -Descending |
Select-Object -First 5 | Format-Table
(filter/sort/select first, format-* absolutely last)
$obj.MethodName without
() describes the method rather than running it (Section 5).Get-Member
is the reliable way to find a property's exact name — property names
are usually not case-sensitive to type, but must otherwise be spelled
exactly as PowerShell defines them.Get-Member (or Select-Object -Property *) shows you
everything that object actually carries, which is often far more than what
appears by default.Select-Object -Property creates a new, simplified object, not a
reference to the original — once you have selected down to a few
properties, the result is a lighter custom object; you cannot then call the
original object's methods on it, because they are gone along with the
properties you didn't select.Object-oriented output is a design choice with real security consequences, mostly upside but with a couple of things worth flagging:
Get-Member is itself a reconnaissance tool, for you and for an
attacker. Discovering an object's full method list is exactly how you
find powerful, sometimes destructive actions you did not know existed —
legitimately useful for administration, and equally useful for an attacker
probing what a script or session can do. Be cautious about which objects
you expose to less-trusted code or users, since Get-Member will happily
reveal everything available on them..Kill(), .Delete(), or similar on an object takes effect
instantly and irreversibly, exactly as if you had run the equivalent
cmdlet — there is no extra confirmation step just because it was invoked
via dot notation rather than a named command. Treat destructive method
calls with the same caution as their cmdlet equivalents (many of which
offer -WhatIf and -Confirm; raw method calls generally do not).-ExpandProperty and property selection can unintentionally simplify
away useful audit data. Trimming an object down to only the columns you
currently care about is convenient, but if that trimmed output is what
gets logged or saved, later investigation may be missing properties nobody
thought to keep — worth erring toward selecting a broader property set for
anything destined for a log or report.Get-Member (gm) lists every property and method an object has,
including each property's data type.$object.PropertyName, or $_.PropertyName inside a
pipeline. Methods: $object.MethodName() — parentheses required even
with no arguments.Sort-Object sorts by real property values (-Property,
-Descending); Select-Object narrows to specific properties
(-Property), limits count (-First), or unwraps raw values
(-ExpandProperty).Format-*
cmdlets convert to display-only output and must go last.| Term | Meaning |
|---|---|
| Object | A bundle of properties (data) and methods (actions). |
| Property | A piece of data an object carries. |
| Method | An action an object can perform. |
| Get-Member | Lists an object's properties and methods. |
| $_ | The current object inside a pipeline. |
| Dot notation | $object.Property / $object.Method() syntax. |
| Sort-Object | Sorts objects by one or more property values. |
| Select-Object | Selects specific properties, or limits/unwraps output. |
| -ExpandProperty | Returns a property's raw value, not a wrapping object. |
| Format-Table / Format-List | Convert objects to display-only output. |
| Display-only object | A Format-* result, not usable by further object-aware cmdlets. |
| Member type | Get-Member's classification (Property, Method, etc.) of an item. |
| TypeName | The full .NET type name of an object, shown by Get-Member. |
$object.PropertyName — e.g. $proc.CPU returns a process's CPU
time. Dot notation for data.$object.MethodName(), with parentheses even for no-argument methods;
forgetting the parentheses just describes the method instead of running
it. A classic silent mistake.Where-Object { $_.CPU -gt 10 }. The pipeline's "this one" variable.Get-Process | Sort-Object -Property WS -Descending | Select-Object -First 5 -Property ProcessName, WS (or the relevant memory property).
Sort, then limit and select.